<?php
App::uses('Sanitize', 'Utility');
class ThreadsController extends AppController {
	public $name = 'Threads';

	public function beforeFilter(){
		$this->Auth->allow('view', 'home', 'search');
		$this->Auth->Authorize = 'controller';
		$this->Security->blackHoleCallback = 'blackhole';
	}

/* Allow ajax requests for preview and formattingHelp methods */
	function blackhole($type) {
		if($this->request->params['action'] == 'preview' && $this->request->is('ajax')){
			return true;
		}
		if($this->request->params['action'] == 'formattingHelp' && $this->request->is('ajax')){
			return true;
		}
		throw new MethodNotAllowedException(__('Nope: ' . $type . ' - ' . Router::url($this->here, true)));
	}

/* Check the user is allowed to post in this sub forum
 * Only allow admins to delete/sticky/lock/setHome threads
 * Only allow edit if thread is owned by user (or mod/admin)
 */
	public function isAuthorized($user) {
		parent::isAuthorized($user);
		if ($this->request->action === 'add') {
			return $this->Thread->SubForum->canPostHere($this->request->params['id']);
		}

		if ($this->request->action === 'sticky' || $this->request->action === 'lock' || $this->request->action === 'setHome'){
			return (AuthComponent::User('role') == '3');
		}

		if ($this->request->action === 'edit') {
			$articleId = $this->request->params['id'];
			return $this->Thread->isOwnedBy($articleId);
		}
		return true;
	}

/* Make sure thread exists, post thread and redirect
 * Set variables for breadcrumbs
 */
	public function add($id = null, $slug = null){
		$this->set('title_for_layout', SITE_NAME . ' &bull; New thread');

		$this->Thread->SubForum->id = $id;
		if(!$this->Thread->SubForum->exists()){
			throw new NotFoundException('Sub forum not found');
		}

		$subForumName = $this->Thread->SubForum->field('name');
		$this->set('subForumName', $subForumName);
		$this->set('subForumId', $this->Thread->SubForum->id);
		$this->set('thread_id', '0');

		if($this->request->is('post') || $this->request->is('put')){
			$this->Thread->Create();
			if($this->Thread->postThread($this->request->data, '0')){
				$this->Session->setFlash('Thread created', 'default', array('class' => 'success'));
				$this->redirect(array('controller' => 'threads', 'action' => 'view', 'id' => $this->Thread->id, 'slug' => Inflector::slug($this->request->data[$this->Thread->alias]['title'])));
			}
		}
	}

/* Set recursive to 0, we only need top level data
 * Set variables for breadcrumbs
 * If a user is already subscribed, check the checkbox
 * unset editreason to force user to enter a new message for each edit
 */
	public function edit($id = null, $slug = null){
		$this->set('title_for_layout', SITE_NAME . ' &bull; Edit thread');

		$this->Thread->id = $id;
		if(!$this->Thread->exists()){
			throw new NotFoundException('Thread not found');
		}

		$this->Thread->recursive = 0;
		$threadData = $this->Thread->read();

		$this->set('threadId', $id);
		$this->set('threadTitle', $threadData[$this->Thread->alias]['title']);
		$this->set('subForumId', $threadData['SubForum']['id']);
		$this->set('subForumName', $threadData['SubForum']['name']);

		if($this->request->is('get')){
			$this->request->data = $this->Thread->read();
			$this->request->data[$this->Thread->alias]['notification'] = $this->Thread->Notification->find('count', array('conditions' => array('thread_id' => $id, 'user_id' => $this->Auth->User('id'))));
			unset($this->request->data[$this->Thread->alias]['editreason']);
			
		}elseif($this->request->is('post') || $this->request->is('put')){
			$threadId = ($this->request->data[$this->Thread->alias]['thread_id'] == '0') ? $id : $this->request->data[$this->Thread->alias]['thread_id'];
			if($this->Thread->editThread($this->request->data, $threadId)){
				$this->Session->setFlash('Thread updated', 'default', array('class' => 'success'));
				$this->redirect(array('controller' => 'threads', 'action' => 'view', 'id' => $threadId, 'slug' => $slug));
			}
		}
	}

/* Check thread exists and is not locked
 * Set recursive to 0, we only need top level data
 * Set variables for breadcrumbs
 * Post reply and update parent with reply details
 */
	public function reply($parentId = null, $quoteId = null, $slug = null){
		$this->set('title_for_layout', SITE_NAME . ' &bull; Reply to thread');

		$this->Thread->id = $parentId;
		if(!$this->Thread->exists()){
			throw new NotFoundException('Thread not found');
		}
		if($this->Thread->locked()){
			throw new NotFoundException('This thread is locked');
		}

		$this->Thread->recursive = 0;
		$threadData = $this->Thread->read();
		$this->set('threadId', $parentId);
		$this->set('threadTitle', $threadData[$this->Thread->alias]['title']);
		$this->set('subForumId', $threadData['SubForum']['id']);
		$this->set('subForumName', $threadData['SubForum']['name']);

		if($this->request->is('get')){
			$this->request->data = $this->Thread->read();
			$this->request->data[$this->Thread->alias]['notification'] = $this->Thread->Notification->find('count', array('conditions' => array('thread_id' => $parentId, 'user_id' => $this->Auth->User('id'))));
			$this->request->data[$this->Thread->alias]['body'] = $this->Thread->getQuotedThread($quoteId);
		}

		if($this->request->is('post') || $this->request->is('put')){
			if($this->Thread->postReply($this->request->data, $parentId)){
				$newThreadId = $this->Thread->id;
				if($this->Thread->updateParent($this->request->data, $parentId, $this->Thread->id)){
					$this->Session->setFlash('Thread created', 'default', array('class' => 'success'));
					$this->redirect(array('controller' => 'threads', 'action' => 'view', 'id' => $parentId, 'slug' => $slug, 'page' => ceil(($threadData[$this->Thread->alias]['reply_count'] + 1) / 10), '#' => $newThreadId));
				}
			}
		}
	}

/* Make sure user is viewing a parent thread
 * whoCanEdit adds a new key to each thread the user is allowed to edit
 * Users who are subscribed get shown to admin
 * If a user is subscribed they get shown an element to unsubscribe - token
 */
	public function view($id = null, $slug = null){
		$this->Thread->id = $id;
		if(!$this->Thread->exists()){
			throw new NotFoundException('Thread not found');
		}
		if($this->Thread->find('count', array('conditions' =>  array('Thread.id' => $id, 'Thread.thread_id' => 0))) === 0){
			throw new NotFoundException('Thread not found');
		}

		$this->Thread->incrementViews();
		$this->paginate = array(
			'conditions' => array('OR' => array(
				'Thread.id' => $id,
				'Thread.thread_id' => $id
			)), 
			'order' => array('Thread.created'),
			'limit' => 10
		);

		$threads = $this->Thread->whoCanEdit($this->paginate('Thread'));
		$subscribedUsers = $this->Thread->Notification->whoIsSubscribed($id);
		$subscribedToken = $this->Thread->Notification->isSubscribed($subscribedUsers);
		$isSubscribed = (isset($subscribedToken)) ? true : false;
		$threadTitle = $threads[0][$this->Thread->alias]['title'];

		$this->set('threads', $threads);
		$this->set('roles', array(1 => 'Member', 2 => 'Moderator', 3 => 'Admin'));
		$this->set('title_for_layout', $threadTitle);
		$this->set('threadTitle', $threadTitle);
		$this->set('isSubscribed' , $isSubscribed);
		$this->set('subscribedToken', $subscribedToken);
		$this->set('subscribedUsers', $subscribedUsers);
	}

	public function search(){
		$this->set('title_for_layout', SITE_NAME . ' &bull; Search results');
		if($this->request->is('get')){
			$threads = $this->Thread->find('all', array('conditions' => array('Thread.thread_id' => '-1')));
			$this->set('threads', $threads);
			$this->set('results', '0');
		}else{
			if(strlen($this->request->data[$this->Thread->alias]['searchquery']) >= 4){
				$threads = $this->Thread->find('all', array(
					'conditions' =>	array(
						'OR' => array(
							array('Thread.title LIKE' => '%' . $this->request->data[$this->Thread->alias]['searchquery'] . '%'),
							array('Thread.body LIKE' => '%' . $this->request->data[$this->Thread->alias]['searchquery'] . '%')
						),
						'AND' => array('Thread.thread_id' => 0)
					),
					'order' => array('Thread.sticky' =>  'DESC', 'Thread.lastpost' =>  'DESC')
				));

				$this->set('threads', $threads);
				$this->set('results', count($threads));
			}else{
				$this->Session->setFlash('Please enter 4 or more characters', 'default', array('class' => 'nodice'));
				$this->redirect($this->referer());
			}
		}
	}

/* Grab all threads that have been marked to show on the homepage
 * Also grab threads assigned to a sub_forum with the id 1
 * Sort threads based on the year they were posted
 */
	public function home(){
		$this->Thread->recursive = 0;
		$oldThreads = $this->Thread->find('all', array(
			'order' => 'Thread.created DESC',
			'conditions' => array(
				'Thread.home' => 1,
		)));


		$years = array();
		foreach($oldThreads as $thread){
			$year = substr($thread[$this->Thread->alias]['created'], 0, 4);
			$oldThreads2[$year][] = $thread;
		}
		$this->set('title_for_layout', SITE_NAME . ' &bull; Home');
		$this->set('years', $years);
		$this->set('latestThread', $oldThreads[0]);
		$this->set('oldThreads', $oldThreads2);
	}

/* Lock/unlock thread and redirect to referer */
	public function lock($id = null, $slug = null){
		$this->Thread->id = $id;
		if(!$this->Thread->exists()){
			throw new NotFoundException('Thread not found');
		}
		$locked = $this->Thread->field('locked', array('id' => $id));
		$locked = ($locked == '0') ? '1' : '0';

		$msg = 'Thread has been ';
		$msg .= ($locked == '0') ? 'unlocked' : 'locked';

		$this->Thread->set('locked', $locked);
		$this->Thread->set('editreason', $msg);
		$this->Thread->set('lasteditor', $this->Auth->User('id'));
		if($this->Thread->save()){
			$this->Session->setFlash($msg, 'default', array('class' => 'success'));
			$this->redirect($this->referer());
		}
		$this->redirect($this->referer());
	}


/* Sticky/unsticky thread and redirect to referer */
	public function sticky($id = null, $slug = null){
		$this->Thread->id = $id;
		if(!$this->Thread->exists()){
			throw new NotFoundException('Thread not found');
		}
		$sticky = $this->Thread->field('sticky', array('id' => $id));
		$sticky = ($sticky == '0') ? '1' : '0';
		$msg = 'Thread has been ';
		$msg .= ($sticky == '0') ? 'unstickied' : 'stickied';

		$this->Thread->set('sticky', $sticky);
		$this->Thread->set('editreason', $msg);
		$this->Thread->set('lasteditor', $this->Auth->User('id'));
		if($this->Thread->save()){
			$this->Session->setFlash($msg, 'default', array('class' => 'success'));
			$this->redirect($this->referer());
		}
		$this->redirect($this->referer());
	}

/* Ajax method used for previewing threads/messages */
	public function preview(){
		$this->autoRender = false;
		if($this->request->is('post') || $this->request->is('ajax')){
			$view = new View($this);
			$markdown = $view->loadHelper('Markdown');
			return json_encode(array('preview' => $markdown->parse($this->request->data['Preview'])));
		}
		return json_encode(array('preview' => 'no dice'));
	}

/* Set a thread to be shown on the homepage
 * Make sure non-parent threads can't be added
 */
	public function setHome($id = null){
		$this->Thread->id = $id;
		if(!$this->Thread->exists()){
			throw new NotFoundException('Thread not found');
		}

		if(!$this->Thread->isParent()){
			throw new MethodNotAllowedException("You can't add non-parent threads to the homepage");
		}

		$newHomeValue = ($this->Thread->field('home', $id) == 0) ? '1' : '0';
		if($this->Thread->saveField('home', $newHomeValue)){
			$this->Session->setFlash(($newHomeValue == '0') ? 'Thread removed from the homepage' : 'Thread added to the homepage', 'default', array('class' => 'success'));
			$this->redirect($this->referer());
		}
		$this->redirect($this->referer());
	}

/* Ajax method to show the formatting help element */
	public function formattingHelp(){
		$this->autoRender = false;
		$data = $this->render(DS . 'Elements' . DS . 'formatting_help', false);
		return $data;
	}

	public function delete(){
		if($this->request->is('get')){
			throw new MethodNotAllowedException();
		}elseif($this->request->is('post')){
			$i = 0;
			foreach($this->request->data[$this->Thread->alias]['selectedThreads'] AS $threadId){
				$this->Thread->delete($threadId);
				$this->Thread->deleteAll(array('Thread.thread_id' => $threadId));
				$i++;
			}
			$this->Session->setFlash($i . ': Threads have been deleted.', 'default', array('class' => 'success'));
			$this->redirect($this->referer());;
		}
	}
}